package com.simple.create.singleton.sample4;

import com.simple.LogUtil;
import com.simple.create.singleton.sample2.Singleton;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author simple
 * @version 1.0
 * @date 2018/12/6 14:44
 * @since 1.0
 */
public class Start {
    private static AtomicInteger count = new AtomicInteger(0);
    private static final int DELAY = 3;
    private static final int LENGTH = 500;
    private static ThreadFactory threadFactory = Executors.defaultThreadFactory();
    private static ExecutorService poolExecutor = new ThreadPoolExecutor(LENGTH, LENGTH * 2,
            10000L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1024), threadFactory, new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) {
        // 不能通过new关键字创建对象(即不能调用构造方法)
        // Singleton instance = new Singleton();
        CountDownLatch latch = new CountDownLatch(1);
        for (int i = 0; i < LENGTH; i++) {
            poolExecutor.execute(new Test(latch));
        }
        try {
            LogUtil.info("开始等待" + DELAY + "秒");
            for (int i = 0; i < DELAY; i++) {
                TimeUnit.SECONDS.sleep(1);
                int j = count.incrementAndGet();
                StringBuilder sb = new StringBuilder();
                sb.append(j).append("秒");
                for (int k = 0; k < j; k++) {
                    sb.append(".");
                }
                LogUtil.info(sb.toString());
            }
            LogUtil.info("准备开始并发....\n");
            TimeUnit.SECONDS.sleep(1);
            latch.countDown();
            LogUtil.info("所有线程开始");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //最后关闭线程池，但执行以前提交的任务，不接受新任务
            poolExecutor.shutdown();
        }
        while (true) {
            if (poolExecutor.isTerminated()) {
                int instanceCount = Singleton.getInstanceCount();
                if (1 != instanceCount) {
                    LogUtil.info("这种单例模式的写法在多线程的情况下有问题, 共创建了" + instanceCount + "个实例");
                } else {
                    LogUtil.info("这种单例模式的写法在多线程的情况下没有问题, 可喜可贺");
                }
                break;
            }
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                LogUtil.info("被打断");
            }
        }
    }
}

class Test implements Runnable {

    private CountDownLatch latch;

    Test(CountDownLatch latch) {
        this.latch = latch;
    }

    @Override
    public void run() {
        try {
            //阻塞当前线程，
            latch.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
        start();
    }

    private void start() {
        Singleton.getInstance();
    }
}